package com.winning.pmph.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.winning.pmph.entity.*;
import com.winning.pmph.mapper.KnowledgeSyncRecordMapper;
import com.winning.pmph.mapper.PlatformKnowledgeLibMapper;
import com.winning.pmph.utils.KnowledgeEditUtil;
import com.winning.pmph.utils.KnowledgeSyncUtil;
import com.winning.pmph.utils.LocalDateTimeUtil;
import com.winning.pmph.utils.RocketMQProducerUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Async
@Component
public class RocketMQProducerService {
    private Log log = LogFactory.getLog(getClass());
    @Lazy
    @Resource
    private KnowledgeLibFieldService knowledgeLibFieldService;
    @Lazy
    @Resource
    private KnowledgeLibService knowledgeLibService;
    @Lazy
    @Resource
    private RuleItemService ruleItemService;
    @Lazy
    @Resource
    private ReleasedKnowledgeService releasedKnowledgeService;
    @Lazy
    @Resource
    private ReleasedKnowledgeFieldService releasedKnowledgeFieldService;
    @Lazy
    @Resource
    private TempKnowledgeService tempKnowledgeService;
    @Lazy
    @Resource
    private KnowledgeSyncRecordMapper knowledgeSyncRecordMapper;
    @Lazy
    @Resource
    private PlatformKnowledgeLibMapper platformKnowledgeLibMapper;

    public void sendKnowledge(String topic, ReleasedKnowledge releasedKnowledge, String username) {
        boolean sendFlag = false;
        JSONObject knowledgeJson = new JSONObject();
        try {
            boolean checkFlag = checkKnowledgeAndParseJson(releasedKnowledge, knowledgeJson);
            if (checkFlag) {
                sendFlag = RocketMQProducerUtil.sendMessage(topic, "knowledge", releasedKnowledge.getName(),
                        knowledgeJson.toJSONString());
            }
        } catch (Exception e) {
            log.error("推送知识异常: ", e);
        }
        // 准备知识同步日志对象, 同步状态对象;
        KnowledgeSyncRecord knowledgeSyncRecord = new KnowledgeSyncRecord();
        knowledgeSyncRecord.setKnowledgeId(releasedKnowledge.getId());
        knowledgeSyncRecord.setVersion(releasedKnowledge.getVersion());
        knowledgeSyncRecord.setPlatformId(topic);
        knowledgeSyncRecord.setOperatedBy(username);
        knowledgeSyncRecord.setOperatedTime(LocalDateTimeUtil.getNowAsString());
        KnowledgeSyncStatus knowledgeSyncStatus = JSON.parseObject(JSON.toJSONString(knowledgeSyncRecord), KnowledgeSyncStatus.class);
        knowledgeSyncStatus.setKnowledgeLibId(releasedKnowledge.getKnowledgeLibId());
        // 改状态;
        if (sendFlag) {
            knowledgeSyncRecord.setSyncFlag(KnowledgeSyncRecord.SYNC_STATUS_SUCCESS);
            knowledgeSyncStatus.setKind(KnowledgeSyncStatus.KIND_SUCCESS);
        } else {
            knowledgeSyncRecord.setSyncFlag(KnowledgeSyncRecord.SYNC_STATUS_FAILURE);
            knowledgeSyncStatus.setKind(KnowledgeSyncStatus.FAILED_KIND_PRODUCER);
        }
        // 记录同步日志, 同步状态;
        knowledgeSyncRecordMapper.saveBean(knowledgeSyncRecord);
        knowledgeLibService.saveKnowledgeSyncStatus(knowledgeSyncStatus);
    }

    public void sendKnowledgeLib(String topic, KnowledgeLib knowledgeLib) {
        JSONObject bodyJson = new JSONObject();
        bodyJson.put("type", "knowledgeLib");
        bodyJson.put("option", "add");
        JSONObject data = new JSONObject();
        data.put("id", knowledgeLib.getId());
        data.put("name", knowledgeLib.getName());
        if (CollectionUtils.isNotEmpty(knowledgeLib.getSpecialtySet())) {
            JSONArray specialtyArray = new JSONArray();
            knowledgeLib.getSpecialtySet().forEach(item -> {
                JSONObject cntSpecialty = new JSONObject();
                cntSpecialty.put("specialtyId", item.getId());
                cntSpecialty.put("specialtyName", item.getName());
                specialtyArray.add(cntSpecialty);
            });
            data.put("specialty", specialtyArray);
        }
        JSONArray field = new JSONArray();
        for (KnowledgeLibField knowledgeLibField : knowledgeLib.getFieldList()) {
            JSONObject cntField = new JSONObject();
            cntField.put("id", knowledgeLibField.getId());
            cntField.put("name", knowledgeLibField.getName());
            cntField.put("index", knowledgeLibField.getIndex());
            if (knowledgeLibField.getKind() == KnowledgeLibField.FIELD_KIND_STRINGTEXT
                    || knowledgeLibField.getKind() == KnowledgeLibField.FIELD_KIND_TEXTAREA
                    || knowledgeLibField.getKind() == KnowledgeLibField.FIELD_KIND_IMG
                    || knowledgeLibField.getKind() == KnowledgeLibField.FIELD_KIND_VIDEO
                    || knowledgeLibField.getKind() == KnowledgeLibField.FIELD_KIND_DROPDOWNLIST) {
                cntField.put("type", "text");
            } else if (knowledgeLibField.getKind() == KnowledgeLibField.FIELD_KIND_RICHEDITOR) {
                cntField.put("type", "rich");
            } else if (knowledgeLibField.getKind() == KnowledgeLibField.FIELD_KIND_MULTI_VALUE_INPUT
                    || knowledgeLibField.getKind() == KnowledgeLibField.FIELD_KIND_DROPMULTILIST
                    || knowledgeLibField.getKind() == KnowledgeLibField.FIELD_KIND_ASSOCIATE_PLATFORM) {
                cntField.put("type", "multi");
            } else if (knowledgeLibField.getKind() == KnowledgeLibField.FIELD_KIND_REFERENCE) {
                cntField.put("type", "tag");
                if (StringUtils.isNotEmpty(knowledgeLibField.getKindValue())){
                    cntField.put("value", knowledgeLibField.getKindValue().replaceAll(",", ";"));
                }
            } else if (Objects.equals(knowledgeLibField.getKind(), KnowledgeLibField.FIELD_KIND_ASSOCIATE_CURRENT_KNOWLEDGE_LIB)
                    || Objects.equals(knowledgeLibField.getKind(), KnowledgeLibField.FIELD_KIND_ASSOCIATE_OTHER_KNOWLEDGE_LIB)) {
                cntField.put("type", "knowledge");
            } else if (knowledgeLibField.getKind() == KnowledgeLibField.FIELD_KIND_FILE) {
                cntField.put("type", "file");
            } else if (knowledgeLibField.getKind() == KnowledgeLibField.CALCULATOR_FIELD_KIND_H5) {
                cntField.put("type", "h5");
            } else {
                cntField.put("type", "unknown");
            }
            field.add(cntField);
        }
        data.put("field", field);
        bodyJson.put("data", data);
        RocketMQProducerUtil.sendMessage(topic, "knowledgeLib", knowledgeLib.getName(),
                bodyJson.toJSONString());
    }

    public void sendTag(String topTagId, Tag tag) {
        // 查询使用改tag的知识库;
        List<KnowledgeLibField> knowledgeLibFields = knowledgeLibFieldService.query().select("distinct knowledge_lib_id").eq("KIND_VALUE", topTagId).list();
        // 查找知识库集合关联的平台id集合
        List<PlatformKnowledgeLib> platformKnowledgeLibs = platformKnowledgeLibMapper.executeMultiSelect(
                "select distinct platform_id from platform_knowledge_lib where knowledge_lib_id in " +
                        knowledgeLibFields.stream().map(KnowledgeLibField::getKnowledgeLibId).collect(Collectors.joining("','", "('", "')")));
        for (PlatformKnowledgeLib platformKnowledgeLib : platformKnowledgeLibs) {
            sendTagToTopic(platformKnowledgeLib.getPlatformId(), tag);
        }
    }

    public void sendTagToTopic(String topic, Tag tag) {
        JSONObject bodyJson = new JSONObject();
        bodyJson.put("type", "tag");
        bodyJson.put("option", StringUtils.isEmpty(tag.getOption()) ? "add" : tag.getOption());
        JSONObject data = new JSONObject();
        data.put("id", tag.getId());
        data.put("name", tag.getName());
        data.put("parent", tag.getParentId());
        data.put("level", tag.getLevel());
        data.put("index", tag.getIndex());
        data.put("root", tag.getRootId());
        data.put("code", tag.getTagCode());
        bodyJson.put("data", data);
        RocketMQProducerUtil.sendMessage(topic, "tag", tag.getName(), bodyJson.toJSONString());
    }

    private boolean checkKnowledgeAndParseJson(ReleasedKnowledge releasedKnowledge, JSONObject knowledgeJson) {
        knowledgeJson.put("type", "knowledge");
        if (Objects.equals(releasedKnowledge.getSyncOperation(), ReleasedKnowledge.SYNC_OPERATION_DELETE)) {
            knowledgeJson.put("option", "delete");
        } else if (Objects.equals(releasedKnowledge.getSyncOperation(), ReleasedKnowledge.SYNC_OPERATION_MODIFY)) {
            knowledgeJson.put("option", "update");
        } else {
            knowledgeJson.put("option", "add");
        }

        JSONObject data = new JSONObject();
        data.put("id", releasedKnowledge.getId());
        data.put("name", releasedKnowledge.getName());
        data.put("version", releasedKnowledge.getVersion());
        data.put("knowledgeLibId", releasedKnowledge.getKnowledgeLibId());
        if (StringUtils.isEmpty(releasedKnowledge.getKnowledgeLibName())) {
            releasedKnowledge.setKnowledgeLibName(knowledgeLibService.getById(releasedKnowledge.getKnowledgeLibId()).getName());
        }
        data.put("knowledgeLibName", releasedKnowledge.getKnowledgeLibName());
        JSONArray field = new JSONArray();
        if (CollectionUtils.isEmpty(releasedKnowledge.getKnowledgeFieldList())) {
            // 给releasedKnowledge对象设置fields
            String sql = "select * from released_knowledge_field where knowledge_id = '" + releasedKnowledge.getId() + "' order by hidden, id";
            List<KnowledgeField> releasedKnowledgeFields = Lists.newArrayList();
            releasedKnowledgeFieldService.getBaseMapper().executeMultiSelect(sql).forEach(releasedKnowledgeFields::add);
            releasedKnowledge.setKnowledgeFieldList(releasedKnowledgeFields);
        }
        // 排序
        KnowledgeEditUtil.resortKnowledgeFields(releasedKnowledge);
        for (int i = 0; i < releasedKnowledge.getKnowledgeFieldList().size(); i++) {
            KnowledgeField knowledgeField = releasedKnowledge.getKnowledgeFieldList().get(i);
            JSONObject cntField = new JSONObject();
            cntField.put("name", knowledgeField.getName());
            cntField.put("displayName", knowledgeField.getDisplayName());
            cntField.put("knowledgeLibFieldId", knowledgeField.getKnowledgeLibFieldId());
            cntField.put("index", i);
            cntField.put("source", KnowledgeSyncUtil.parseKnowledgeFieldSource(knowledgeField.getSource()));
            String value = null;
            if (knowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_STRINGTEXT
                    || knowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_TEXTAREA) {
                cntField.put("type", "text");
                value = knowledgeField.getProperty();
            }
            // 图片类型, 数据库存储为jsonStr, 转为html标签;
            else if (knowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_IMG){
                cntField.put("type", "text");
                value = KnowledgeSyncUtil.parseKnowledgeFieldImageType(knowledgeField.getProperty());
            }
            // 视频字段, 数据库存储为jsonStr, 转为html标签;
            else if (knowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_VIDEO){
                cntField.put("type", "text");
                value = KnowledgeSyncUtil.parseKnowledgeFieldVideoType(knowledgeField.getProperty());
            }
            else if (knowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_DROPDOWNLIST) {
                cntField.put("type", "text");
                RuleItem ruleItem = ruleItemService.getById(knowledgeField.getProperty());
                if (Objects.nonNull(ruleItem)) {
                    value = ruleItem.getName();
                }
            } else if (knowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_RICHEDITOR) {
                cntField.put("type", "rich");
                value = knowledgeField.getProperty();
            } else if (knowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_MULTI_VALUE_INPUT) {
                cntField.put("type", "multi");
                JSONArray jsonArray = JSON.parseArray(knowledgeField.getProperty());
                if (CollectionUtils.isNotEmpty(jsonArray) && jsonArray.size() > 0) {
                    value = jsonArray.stream().map(Object::toString).collect(Collectors.joining(";"));
                }
            } else if (knowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_DROPMULTILIST) {
                cntField.put("type", "multi");
                List<String> ruleItemIdList = JSON.parseArray(knowledgeField.getProperty(), String.class);
                if (ruleItemIdList.size() > 0) {
                    value = ruleItemService.getBaseMapper().selectBatchIds(ruleItemIdList).stream().map(RuleItem::getName).collect(Collectors.joining(";"));
                }
            } else if (knowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_REFERENCE) {
                cntField.put("type", "tag");
                // tag 数据库存储为双层数组, [['0001AA1000000009KGGP','0001AA1000000009KGGQ','0001AA1000000009KGGU','0001AA1000000009KGHZ']], 只取叶子节点;
                String property = knowledgeField.getProperty();
                ArrayList<String> parsedList = Lists.newArrayList();
                JSONArray outerArray = JSONArray.parseArray(property);
                if (CollectionUtils.isNotEmpty(outerArray)) {
                    for (int j = 0; j < outerArray.size(); j++) {
                        JSONArray innerArray = outerArray.getJSONArray(j);
                        if (CollectionUtils.isNotEmpty(innerArray)) {
                            parsedList.add(innerArray.getString(innerArray.size() - 1));
                        }
                    }
                }
                value = parsedList.stream().collect(Collectors.joining(";"));
            }
            // 关联知识, 数据库存储格式为: [{"name":"12901","id":"0001AA100000000LDWKH"},{"name":"13001","id":"0001AA100000000LDZPW"}]
            else if (knowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_ASSOCIATE_CURRENT_KNOWLEDGE_LIB
                    || knowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_ASSOCIATE_OTHER_KNOWLEDGE_LIB) {
                cntField.put("type", "knowledge");
                JSONArray jsonArray = JSON.parseArray(knowledgeField.getProperty());
                if (CollectionUtils.isNotEmpty(jsonArray)){
                    for (int j = jsonArray.size() - 1; j >= 0; j--) {
                        JSONObject jsonObject = jsonArray.getJSONObject(j);
                        String knowledgeId = jsonObject.getString("id");
                        Knowledge associateKnowledge = releasedKnowledgeService.getById(knowledgeId);
                        if (Objects.isNull(associateKnowledge)) {
                            associateKnowledge = tempKnowledgeService.getById(knowledgeId);
                        }
                        if (Objects.nonNull(associateKnowledge)) {
                            jsonObject.put("name", associateKnowledge.getName());
                        } else {
                            jsonArray.remove(j);
                        }
                    }
                }
                if (CollectionUtils.isNotEmpty(jsonArray)) {
                    value = jsonArray.toJSONString();
                }
            } else if (knowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_FILE) {
                cntField.put("type", "file");
                if (CollectionUtils.isNotEmpty(JSON.parseArray(knowledgeField.getProperty()))){
                    value = knowledgeField.getProperty();
                }
            }
            // 计算器专有属性, h5
            else if (knowledgeField.getKind() == KnowledgeLibField.CALCULATOR_FIELD_KIND_H5) {
                cntField.put("type", "h5");
                value = knowledgeField.getProperty();
            } else {
                cntField.put("type", "unknown");
            }
            // todo 发送给助手的类型还包括【医学计算器类型】和【诊断流程图】。这两个类型需要单独考虑如何构造消息
            // 如果字段必填校验;
            if(knowledgeField.getRequired() && StringUtils.isEmpty(value)){
                log.error("同步知识:" + releasedKnowledge.getName() + ", 校验知识完整性失败, 失败原因: 字段(" + knowledgeField.getName() + ", 值为空);");
                return false;
            }
            // 如果value不为空, 则添加到json;
            if (StringUtils.isNotEmpty(value)) {
                cntField.put("value", value);
                field.add(cntField);
            }
        }
        data.put("field", field);
        knowledgeJson.put("data", data);
        return true;
    }
}
